package com.genersoft.iot.vmp.baidu;

import com.genersoft.iot.vmp.baidu.bean.DeviceRemark;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class WatermarkUtils {
    private static final int MARGIN = 20;//距离图片底部大小
    private static int RADIAN;//弧度长度和宽度
    private static int RADIANHALF;//弧度长度和宽度的一半
    private static final int GAP=50;//时间水印内容距离水印画布的距离 和 水印画布距离图片右边的距离

    public static void main(String[] args) throws Exception {
//        String srcImgPath = "D:\\Project\\wvp-pro-talk\\image\\越界\\20231205190643VCA_TRAVERSE_PLANE.jpg";
//
//        FileInputStream inputStream = new FileInputStream(srcImgPath);
//        DeviceRemark remark = new DeviceRemark();
//        remark.setDeviceName("F51393461");
//        remark.setDeviceId("34020000001320002005");
//        remark.setTime(DateUtil.getNow());
//        remark.setAddress("192.168.3.122");
//
//        addWatermark(inputStream,remark,srcImgPath);

    }

    public static void addWatermark(String srcImgPath , Device device,String alarmTime) {

        try {
            System.out.println("处理水印开始时间-----:"+  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
            FileInputStream inputStream = new FileInputStream(srcImgPath);
            DeviceRemark remark = new DeviceRemark();
            remark.setDeviceName(device.getName());
            remark.setDeviceId(device.getDeviceId());
            remark.setTime(DateUtil.getNow());
            remark.setAlarmTime(alarmTime);
            remark.setAddress(device.getIp());
            if (device.getType() ==1){
                remark.setType("进入区域");
            }
            if (device.getType() ==2){
                remark.setType("离开区域");
            }
            if (device.getType() ==3){
                remark.setType("人脸识别");
            }
            //把文件转换成图片
            Image srcImg = ImageIO.read(inputStream);
            //获取图片的宽和高
            int srcImgwidth = srcImg.getWidth(null);
            int srcImgheight = srcImg.getHeight(null);
            //画水印需要一个画板    创建一个画板
            BufferedImage buffImg = new BufferedImage(srcImgwidth, srcImgheight, BufferedImage.TYPE_INT_RGB);
            //创建一个2D的图像
            Graphics2D g = buffImg.createGraphics();
            //画出来
            g.drawImage(srcImg, 0, 0, srcImgwidth, srcImgheight, null);
            //文字边缘平滑
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            //图片边缘平滑
            g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //水印内容文字字体
            int contextFontSize = (int)(srcImgheight * 0.02);
            Font contextFont = new Font("宋体", Font.BOLD, contextFontSize);
            g.setFont(contextFont);
            //起始横坐标
            int initX = (int)(srcImgwidth * 0.02); //从左往右 横轴 的左边距百分比 width / 100 * 2
            //水印文字的起始横坐标。
            int initFontX =initX +10;//距离水印画布一定距离
            //起始纵坐标。
            int initY = 0;
            //水印画布宽度
            int titleWidth  = 0;
            //处理水印画布宽度。要求:时间不能换行
            //获取时间水印文字的长度。也就是水印画布宽度
            int dateSyWidth =getDateSyWidth(initFontX,remark,g);
            // 起始横坐标+水印画布宽度+水印画布距离图片右边的距离。用于和图片宽度作比较
            int dateSyAllWidth =initX+dateSyWidth+GAP;
            boolean flag = false;//循环是否结束
            for(;;) {
                if(srcImgwidth > dateSyAllWidth) {//如果图片宽度 大于
                    flag =true;
                }else {//小与的话。将字体缩小 重新计算时间水印文字的长度。
                    contextFontSize = (int)(contextFontSize * 0.7);
                    contextFont = new  Font("隶书", Font.BOLD, contextFontSize);
                    g.setFont(contextFont);
                    dateSyWidth = getDateSyWidth(initFontX,remark,g);
                    dateSyAllWidth = initX +dateSyWidth +50;
                }
                if(flag) {
                    break;
                }
            }
            titleWidth =dateSyWidth;

            RADIAN =(int) (titleWidth*0.05);//弧度圆的直径 和水印宽度比为1.0.05
            //使RADIAN为偶数
            if(RADIAN % 2 != 0) {
                RADIAN =RADIAN + 1;
            }
            RADIANHALF = (int)(RADIAN*0.5);//弧度圆的半径

            int interval = contextFontSize/4; //行与行之间间距
            List<String> contestTitleList = contestTitleList(remark);//标题内容
            List<String> contextFontList = contextFontList(remark);//水印内容
            List<String> contextBuildFontList = contextBuildFontList(remark);//水印建设单位内容

            //获取标题高度
            boolean contestflag = false;
            boolean blankFlag = false;
            int titleHeight = handContextHeight(contestTitleList,titleWidth,initFontX,contextFontSize,interval,contestflag,blankFlag,g);
            //水印内容高度
            contestflag = true;
            blankFlag = true;
            int contextHeight = handContextHeight(contextFontList,titleWidth,initFontX,contextFontSize,interval,contestflag,blankFlag,g);//确定内容高度
            //获取底部 水印部分高度
            contestflag = false;
            blankFlag = true;
            int lastContextHeight = handContextHeight(contextBuildFontList,titleWidth,initFontX,contextFontSize,interval, contestflag,blankFlag,g);
            //确定起始纵坐标  (图片高度 - 标题高度 - 内容高度 - 最后内容高度 -底部距离)
            initY = srcImgheight - titleHeight - contextHeight - lastContextHeight - MARGIN;

            //标题部分 start
            Color color = new Color(30,144,255);//背景颜色 1E90FF
            g.setColor(color);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.6F));//设置透明度

            //左上角 弧
            g.fillArc(initX,  initY, RADIAN, RADIAN, 90, 90);
            //右上角 弧
            int hX = initX+titleWidth-RADIAN;
            g.fillArc(hX,  initY, RADIAN, RADIAN, 0, 90);
            //两个弧之间矩形
            int  titlReX = initX+RADIANHALF;
            int  titlReWidth= titleWidth-RADIAN;
            g.fillRect(titlReX,initY, titlReWidth, RADIANHALF);
            //标题部分
            g.fillRect(initX,initY+RADIANHALF, titleWidth, titleHeight-RADIANHALF);

            //具体文字处理
            g.setFont(contextFont);
            color = new Color(255,255,255);//字体颜色 白色
            g.setColor(color);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0F));//设置透明度
            int titleY =initY+RADIANHALF;
            blankFlag = false;
            handContextFont(contestTitleList,initFontX,titleY,contextFontSize,titleWidth,interval,blankFlag,buffImg,g);

            //标题部分 end

            //内容部分 start
            int contextX = initX; //横坐标  和起始横坐标一致
            int contextY = initY + titleHeight;//内容纵坐标。   起始纵坐标 + 标题的高度(logo图片的高度)

            color = new Color(220,220,220);//背景 灰色
            g.setFont(contextFont);
            g.setColor(color);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.6F));
            g.fillRect(contextX ,contextY, titleWidth, contextHeight);

            //具体内容文字
            Color fontColor = new Color(0,0,0);//字体黑色
            g.setColor(fontColor);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0F));//设置透明度

            blankFlag = true;
            handContextFont(contextFontList,initFontX,contextY,contextFontSize,titleWidth,interval,blankFlag,buffImg,g);
            //内容部分 end


            //最后底座 start
            int lastY =initY + titleHeight + contextHeight; //最后建设单位起始纵坐标
            int lastContextHeight1 = lastContextHeight-RADIAN;
            color = new Color(30,144,255);//背景颜色 1E90FF
            g.setColor(color);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.6F));
            g.fillRect(contextX ,lastY , titleWidth, lastContextHeight1);
            //左下角弧度
            int hLY =lastY+lastContextHeight1-RADIANHALF;
            g.fillArc(initX,  hLY, RADIAN, RADIAN, 180, 90);

            //右下角弧度
            g.fillArc(hX,  hLY, RADIAN, RADIAN, 270, 90);
            //之间的矩形
            int hLY1 = hLY+RADIANHALF;
            g.fillRect(titlReX,hLY1, titlReWidth, RADIANHALF);


            //具体文字
            g.setFont(contextFont);
            color = new Color(255,255,255);//字体颜色 白色
            g.setColor(color);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0F));//设置透明度
            blankFlag = true;

            handContextFont(contextBuildFontList,initFontX,lastY,contextFontSize,titleWidth,interval,blankFlag,buffImg,g);
            //最后底座 end

            System.out.println("水印添加完成1");
            System.out.println("处理水印结束时间-----:"+  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));

            int dot = srcImgPath.lastIndexOf('.');
            String extension = (dot == -1) ? "" : srcImgPath.substring(dot+1);//源文件后缀
            OutputStream os = new FileOutputStream(srcImgPath);
            ImageIO.write(buffImg, extension, os);

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(buffImg, extension, bos);

        }catch (Exception e) {
            // TODO: handle exception
        }
    }


    /**
     * 处理水印内容文字
     * @param contextFontList 水印具体内容
     * @param contextX 起始横位置
     * @param contextY 起始纵坐标
     * @param fontSize 字体大小
     * @param titleWidth 水印画布宽度
     * @param interval 行与行之间间隔
     * @param blankFlag 换行是否需要重新计算X坐标。因为标题（项目名称）是没有前缀的。所以标题是高度是false。水印内容和底部是true
     * @param buffImg
     * @param g
     */
    private static void handContextFont(List<String> contextFontList, int contextX, int contextY, int fontSize,
                                        int titleWidth, int interval,Boolean blankFlag,BufferedImage buffImg, Graphics2D g) {

        int tempCharLen = 0;//单字符长度
        int tempLineLen = 0;//单行字符总长度临时计算
        int contextFontHeight = contextY + fontSize;//内容起始位置
        int contextLineX =0;//换行之后的X坐标
        String contextStr = "";
        for(int j=0;j<contextFontList.size();j++) {
            contextLineX = contextX;
            tempLineLen = contextX;
            if(j!=0) {
                contextFontHeight = contextFontHeight+interval+fontSize;
            }

            contextStr = contextFontList.get(j);
            boolean falg = false;
            if(contextStr.startsWith("时间") || contextStr.startsWith("设备编号")) {
                falg =true;
            }
            StringBuffer stringBuffer = new StringBuffer();
            for (int i = 0; i < contextStr.length(); i++) {
                char tempChar = contextStr.charAt(i);
                tempCharLen =getCharLen(tempChar, g);
                tempLineLen += tempCharLen;
                if(tempLineLen>titleWidth) {//换行
                    tempLineLen = 0;
                    //绘制前一行
                    g.drawString(stringBuffer.toString(), contextLineX, contextFontHeight);
                    //绘制完前一行。清空内容,重新追加
                    stringBuffer.delete(0, stringBuffer.length());
                    //满一行 高度就加  (上一行的纵坐标 + 字体大小 + 行的间隔 = 下一行的纵坐标)
                    contextFontHeight = contextFontHeight + fontSize+interval;
                    //重新确定x坐标。
                    if(blankFlag) {//换行重新确定X坐标
                        String title="项: ";
                        char tempChar1= title.charAt(0);
                        int  CharLen =getCharLen(tempChar1, g);
                        char mhtempChar = title.charAt(1);
                        int  mhCharLen =getCharLen(mhtempChar, g);

                        char kgtempChar = title.charAt(2);
                        int  kgCharLen =getCharLen(kgtempChar, g);
                        int linex = 0;
                        if(falg) {
                            linex = contextX+CharLen*2+mhCharLen+kgCharLen; //下一行起始x坐标  上一行x起始坐标+单个字符长度*2+冒号(:)字符长度 + 空格字符长度
                        }else {
                            linex = contextX+CharLen*4+mhCharLen+kgCharLen; //下一行起始x坐标  上一行x起始坐标+单个字符长度*4+冒号(:)字符长度 + 空格字符长度
                        }
                        contextLineX = linex;//下一行的起始位置 变成
                        tempLineLen =linex+tempCharLen;//单行临时长度 也跟着变化
                    }else {
                        tempLineLen =contextX+tempCharLen;
                    }
                    stringBuffer.append(tempChar);
                }
                stringBuffer.append(tempChar);
            }
            g.drawString(stringBuffer.toString(), contextLineX, contextFontHeight);
        }


    }


    /**
     * 获取具体画布高度
     * @param contL 水印内容
     * @param titleWidth 画布宽度
     * @param initX 水印内容文字起始横坐标
     * @param contextFontSize 字体大小
     * @param interval 行与行之间间隔
     * @param contextflag 是否是水印具体内容。因为内容中是没有 画弧度的。计算高度时加 RADIAN（弧度直径）为ture。 标题和顶部有画 弧度计算高度要加RADIAN 为false
     * @param blankFlag 换行是否需要重新计算X坐标。因为标题（项目名称）是没有前缀的。所以标题是高度是false。水印内容和底部是true
     * @param g
     * @return
     */
    private static int handContextHeight(List<String> contL, int titleWidth, int initX, int contextFontSize,
                                         int interval, boolean contextflag, boolean blankFlag,Graphics2D g) {

        String contextStr = "";
        int count = 0;//有多少行
        int tempCharLen = 0;//单字符长度
        int tempLineLen = initX;//单行字符总长度临时计算
        for(int j=0;j<contL.size();j++) {
            tempLineLen = initX;
            contextStr = contL.get(j);
            boolean falg = false;//判断是否是 时间和地点列。如果是:重新计算X坐标时,单个字符长度*2。 不是:重新计算X坐标时,单个字符长度*4。
            if(contextStr.startsWith("截图时间") || contextStr.startsWith("报警时间") || contextStr.startsWith("地点")) {
                falg =true;
            }
            for (int i = 0; i < contextStr.length(); i++) {
                char tempChar = contextStr.charAt(i);

                tempCharLen =getCharLen(tempChar, g);
                tempLineLen += tempCharLen;
                if(tempLineLen>titleWidth) {
                    count++;
                    //重新确定x起始位置
                    if(blankFlag) {
                        String title="项: ";
                        char strtempChar = title.charAt(0);
                        int  CharLen =getCharLen(strtempChar, g);
                        char mhtempChar = title.charAt(1);
                        int  mhCharLen =getCharLen(mhtempChar, g);

                        char kgtempChar = title.charAt(2);
                        int  kgCharLen =getCharLen(kgtempChar, g);
                        if(falg) {
                            int linex = initX+CharLen*2+mhCharLen+kgCharLen; //下一行起始x坐标  上一行x起始坐标+单个字符长度*2+冒号(:)字符长度 + 空格字符长度
                            tempLineLen =linex+tempCharLen;
                        }else {
                            int linex = initX+CharLen*4+mhCharLen+kgCharLen; //下一行起始x坐标  上一行x起始坐标+单个字符长度*4+冒号(:)字符长度 + 空格字符长度
                            tempLineLen =linex+tempCharLen;
                        }

                    }else {
                        tempLineLen = initX+tempCharLen;
                    }

                }
            }
            count++;
        }
        int intervalSize = (count-1)*interval;//行与行之间的间隔
        int ContextHeight = 0;//画布高度
        if(contextflag) {
            ContextHeight = count*contextFontSize+intervalSize+interval; //行数*字体大小+所有行与行之间的间隔 +行与行之间的间隔
        }else {
            ContextHeight = count*contextFontSize+intervalSize+RADIAN; //行数*字体大小+所有行与行之间的间隔 +弧度圆直径
        }

        return ContextHeight;

    }



    /**
     * 整理水印具体内容-- 项目名称
     * @param remark 水印实体
     * @return
     */
    public static List<String> contextFontList(DeviceRemark remark){
        List<String> contL=new ArrayList<String>();
        if(StringUtils.isNotEmpty(remark.getTime())) {//时间
            contL.add("截图时间: "+remark.getTime());
        }
        if(StringUtils.isNotEmpty(remark.getAlarmTime())) {//时间
            contL.add("报警时间: "+remark.getAlarmTime());
        }
        if(StringUtils.isNotEmpty(remark.getAddress())) {//地点
            contL.add("设备IP: "+remark.getAddress());
        }
        if(StringUtils.isNotEmpty(remark.getType())) {//地点
            contL.add("触发方式: "+remark.getType());
        }
        return contL;
    }

    /**
     * 整理水印标题内容-- 项目名称
     * @param remark 水印实体
     * @return
     */
    private static List<String> contestTitleList(DeviceRemark remark) {
        List<String> contextBuildFontList = new ArrayList<String>();
        contextBuildFontList.add("设备序列号: "+remark.getDeviceName());
        return contextBuildFontList;
    }

    /**
     * 整理水印底部内容-- 建设单位
     * @param remark 水印实体
     * @return
     */
    private static List<String> contextBuildFontList(DeviceRemark remark) {
        List<String> contextBuildFontList = new ArrayList<String>();
        contextBuildFontList.add("设备编号: "+remark.getDeviceId());
        return contextBuildFontList;
    }

    /**
     *
     * getDateSyWidth 获取水印内容时间那一行的长度
     * @param initFontX 内容起始横坐标
     * @param remark 水印实体
     * @param g
     * @return
     */
    private static int getDateSyWidth(int initFontX, DeviceRemark remark, Graphics2D g) {
        String time = "时间: "+remark.getTime();
        int dateSyWidth = initFontX+GAP;//水印内容时间那一行起始长度为:起始横坐标+时间水印内容距离水印画布的距离
        for (int i = 0; i < time.length(); i++) {
            char tempChar = time.charAt(i);
            int tempCharLen =getCharLen(tempChar, g);
            dateSyWidth += tempCharLen;
        }
        return dateSyWidth;
    }

    /**
     * @Title: getCharLen
     * @Description: 获取字符长度
     * @param @param c
     * @param @return    参数
     * @return int    返回类型
     * @throws
     */
    public static int getCharLen(char c, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charWidth(c);
    }
}
